#include "bsp_key.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"
#include "bsp_keyfilter.h"  //没有包含bsp_epittimer.h头文件

/**
 *  @brief  关闭定时器
 *  @param  无
 *  @retval 无
 */
void filtertimer_stop(void)
{
    EPIT1->CR &= ~(1<<0);      //关闭定时器
}

/**
 *  @brief  EPIT1中断处理函数
 *  @param  无
 *  @retval 无
 */
void filtertimer_irqhandler(void)
{
    static uint8_t state=OFF;

    if(EPIT1->SR & (1<<0))  //判断比较事件是否发生
    {   
        filtertimer_stop();       //关闭定时器            会在按键中断中开启定时器
        if(gpio_pinread(GPIO1,18)==0)
        {   //抖动期过后,如果还是低电平的话  就该动作了
            state=!state;
            beep_switch(state);
        }
    }
    EPIT1->SR |= (1<<0);   //清除中断标志位
}

/**
 *  @brief        初始化用于消抖的定时器 默认关闭定时器
 *  @param  value 定时器EPIT计数值
 *  @retval       无
 */
void filtertimer_init(uint32_t value)
{
    EPIT1->CR=0;   //先清零CR寄存器
    /**
     * CR寄存器:
     * bit25:24     01时钟源选择Peripheral clock=66MHz
     * bit15:4      frac 分频值
     * bit3:        1 当计数器到0的话从LR重新加载数值   set-and-forget模式  当计数器计数到0,那么就会从加载寄存器EPITx_LR中重新加载数据到计数器中
     * bit2:        1 比较中断使能
     * bit1:        1 初始计数值来源于LR寄存器值
     * bit0:        0 先关闭EPIT1        
     */
    EPIT1->CR=(1<<24 | 1<<3 | 1<<2 | 1<<1);
    EPIT1->LR=value;    //加载寄存器值    加载寄存器EPITx_LR
    EPIT1->CMPR=0;      //比较寄存器值    就是从valu开始相减,减到0时就产生中断
    GIC_EnableIRQ(EPIT1_IRQn);  //使能EPIT1输出比较中断   相当于使能总中断

    /*注册中断服务函数*/
    system_register_irqhandler(EPIT1_IRQn,(system_irq_handler_t)filtertimer_irqhandler,NULL);
}

/**
 *  @brief  重启定时器     其实就是对LR计数值重装
 *  @param  value 定时器EPIT计数值
 *  @retval 无 
 */
void filtertimer_restart(uint32_t value)
{
    EPIT1->CR &= ~(1<<0);  //关闭定时器
    EPIT1->LR = value;     //计数值
    EPIT1->CR |= (1<<0);   //打开定时器
}

/**
 *  @brief  GPIO中断处理函数
 *  @param  无
 *  @retval 无 
 */
void gpio1_16_31_irqhandler(void)
{
    filtertimer_restart(66000000/100);
    gpio_clearintflags(GPIO1,18);   //清除中断标志  中断发生完成之后一定得清除中断标志为位
}


/**
 *  @brief  按键初始化
 *  @param  无
 *  @retval 无
 */
void filterkey_init(void)
{
    gpio_pin_config_t key_config;  //方向  电平  中断方式

    /*1.设置IO复用  GPIO也是复用功能中的一种*/
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);  //将输出关闭就是输入吗???  对了还得设置方向       设置复用为什么功能
    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);  //22K电阻上拉 拉   100MHz  输出失能    再来对复用的功能进行设置

    /*2.初始化GPIO为中断模式    设置输出的方向  和中断的方式*/
    key_config.direction=kGPIO_DigitalInput;
    key_config.interruptMode=kGPIO_IntFallingEdge;  //下降沿中断
    key_config.outputLogic=1;
    gpio_init(GPIO1,18,&key_config);  //但还没有开启中断

    /*3.使能GIC中断,注册中断服务函数,使能GPIO中断*/
    GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); //这里类是于  NVIC中的中断      使能GPIO_IO18所对应的中断总开关
                                              //这里是将gpio1_16_31_irqhandler转换成 system_irq_handler_t类型的指针
    system_register_irqhandler(GPIO1_Combined_16_31_IRQn,(system_irq_handler_t)gpio1_16_31_irqhandler,NULL);  //用户参数为NULL
    //上面主要是给 /*中断服务函数表*/  初始化 赋值

    gpio_enableint(GPIO1,18);                 //这里表示具体的中断
    //上面只是将按键的下降沿中断初始化好了
    filtertimer_init(66000000/100);           //初始化定时器,10ms  这里只是初始化,但还没有开启定时器
}